/* eslint-disable no-restricted-globals */
/* eslint-disable no-case-declarations */
/* eslint-disable no-use-before-define */
/* eslint-disable no-plusplus */
/* eslint-disable no-param-reassign */
import * as _ from 'lodash';
import { DefaultOpts, IMonacoVersion, IParserType } from './default-opts';
import childThread from "./parser.worker";
import { ICompletionItem, ITableInfo, reader, ICursorInfo } from '../sql-parser';
import SQLSnippets from "../../MonacoEditor/snippets";
import { mysqlParser } from "../sql-parser";
import genericAutocompleteParser from "../../generic/genericAutocompleteParser"
const supportedMonacoEditorVersion = ['0.13.2', '0.15.6'];


export async function monacoSqlAutocomplete(
	monaco: any,
	editor: any,
	snippets: SQLSnippets,
	opts?: Partial<DefaultOpts>
) {
	opts = _.defaults(opts || {}, new DefaultOpts(monaco, snippets));

	if (supportedMonacoEditorVersion.indexOf(opts.monacoEditorVersion) === -1) {
		throw Error(
			`monaco-editor version ${opts.monacoEditorVersion
			} is not allowed, only support ${supportedMonacoEditorVersion.join(
				" "
			)}`
		);
	}

	// Get parser info and show error.
	let currentParserPromise: any = null;
	let editVersion = 0;

	editor.onDidChangeModelContent((event: any) => {
		editVersion++;
		const currentEditVersion = editVersion;

		currentParserPromise = new Promise((resolve) => {
			setTimeout(() => {
				const model = editor.getModel();

				asyncParser(
					editor.getValue(),
					model.getOffsetAt(editor.getPosition()),
					opts.parserType
				).then((parseResult) => {
					resolve(parseResult);

					if (currentEditVersion !== editVersion) {
						return;
					}

					opts.onParse(parseResult);

					if (parseResult.error) {
						// const newReason =
						// 	parseResult.error.reason === "incomplete"
						// 		? `Incomplete, expect next input: \n${parseResult.error.suggestions
						// 				.map((each: any) => {
						// 					return each.value;
						// 				})
						// 				.join("\n")}`
						// 		: `Wrong input, expect: \n${parseResult.error.suggestions
						// 				.map((each: any) => {
						// 					return each.value;
						// 				})
						// 				.join("\n")}`;

						// const errorPosition = parseResult.error.token
						// 	? {
						// 			startLineNumber: model.getPositionAt(
						// 				parseResult.error.token.position[0]
						// 			).lineNumber,
						// 			startColumn: model.getPositionAt(
						// 				parseResult.error.token.position[0]
						// 			).column,
						// 			endLineNumber: model.getPositionAt(
						// 				parseResult.error.token.position[1]
						// 			).lineNumber,
						// 			endColumn:
						// 				model.getPositionAt(
						// 					parseResult.error.token.position[1]
						// 				).column + 1,
						// 	  }
						// 	: {
						// 			startLineNumber: 0,
						// 			startColumn: 0,
						// 			endLineNumber: 0,
						// 			endColumn: 0,
						// 	  };

						// model.getPositionAt(parseResult.error.token);

						// monaco.editor.setModelMarkers(model, opts.language, [
						// 	{
						// 		...errorPosition,
						// 		message: newReason,
						// 		severity: getSeverityByVersion(
						// 			monaco,
						// 			opts.monacoEditorVersion
						// 		),
						// 	},
						// ]);
					} else {
						monaco.editor.setModelMarkers(
							editor.getModel(),
							opts.language,
							[]
						);
					}
				});
			});
		});
	});


	debugger
	var fizzCommand = editor.createContextKey("fizzCommand", true);
	editor.addCommand(
		{
			id: "fizzCommand",
		},
		(ds) => {
			const currentModel = editor.getModel();

			const lineCount = currentModel.getLineCount();
			const valueLength = currentModel.getValueLength();
			const options = currentModel.getOptions();
			alert(`Fizz Command:
          行数: ${lineCount},
          内容长度: ${valueLength},
        `);
		}
	);




	monaco.languages.registerCompletionItemProvider(opts.language, {
		triggerCharacters:
			"$.,:{}=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split(
				""
			),
		provideCompletionItems: async (model, position) => {
			const { lineNumber, column } = position;
			// 光标前文本
			const textBeforePointer = model.getValueInRange({
				startLineNumber: lineNumber,
				startColumn: 0,
				endLineNumber: lineNumber,
				endColumn: column,
			});
			const textBeforePointerMulti = model.getValueInRange({
				startLineNumber: 1,
				startColumn: 0,
				endLineNumber: lineNumber,
				endColumn: column,
			});
			//光标后文本
			const textAfterPointer = model.getValueInRange({
				startLineNumber: lineNumber,
				startColumn: column,
				endLineNumber: lineNumber,
				endColumn: model.getLineMaxColumn(model.getLineCount())
			})
			const textAfterPointerMulti = model.getValueInRange({
				startLineNumber: lineNumber,
				startColumn: column,
				endLineNumber: model.getLineCount(),
				endColumn: model.getLineMaxColumn(model.getLineCount()),
			});
		
			let result = genericAutocompleteParser.parseSql(
				textBeforePointerMulti,
				textAfterPointerMulti
			);

			console.log(result);
			let suggestions = [];
			await opts?.update(result, suggestions);
			return returnCompletionItemsByVersion(
				suggestions,
				opts.monacoEditorVersion
			)

		}
	});

	// monaco.languages.registerHoverProvider(opts.language, {
	// 	provideHover: async (model: any, position: any) => {
	// 		const parseResult: IParseResult = await asyncParser(
	// 			editor.getValue(),
	// 			model.getOffsetAt(position),
	// 			opts.parserType
	// 		);

	// 		const cursorInfo = await reader.getCursorInfo(
	// 			parseResult.ast,
	// 			parseResult.cursorKeyPath
	// 		);

	// 		if (!cursorInfo) {
	// 			return null as any;
	// 		}

	// 		let contents: any = [];

	// 		switch (cursorInfo.type) {
	// 			case "tableField":
	// 				const extra = await reader.findFieldExtraInfo(
	// 					parseResult.ast,
	// 					cursorInfo,
	// 					opts.onSuggestTableFields,
	// 					parseResult.cursorKeyPath
	// 				);
	// 				contents = await opts.onHoverTableField(
	// 					cursorInfo.token.value,
	// 					extra
	// 				);
	// 				break;
	// 			case "tableFieldAfterGroup":
	// 				const extraAfter = await reader.findFieldExtraInfo(
	// 					parseResult.ast,
	// 					cursorInfo,
	// 					opts.onSuggestTableFields,
	// 					parseResult.cursorKeyPath
	// 				);
	// 				contents = await opts.onHoverTableField(
	// 					cursorInfo.token.value,
	// 					extraAfter
	// 				);
	// 				break;
	// 			case "tableName":
	// 				contents = await opts.onHoverTableName(
	// 					cursorInfo as ICursorInfo
	// 				);
	// 				break;
	// 			case "functionName":
	// 				contents = await opts.onHoverFunctionName(
	// 					cursorInfo.token.value
	// 				);
	// 				break;
	// 			default:
	// 		}

	// 		return {
	// 			range: monaco.Range.fromPositions(
	// 				model.getPositionAt(cursorInfo.token.position[0]),
	// 				model.getPositionAt(cursorInfo.token.position[1] + 1)
	// 			),
	// 			contents,
	// 		};
	// 	},
	// });
}

// 实例化一个 worker
const worker: Worker = childThread() as Worker;

let parserIndex = 0;

const asyncParser = async (text: string, index: number, parserType: IParserType) => {
	// parserIndex++;
	// const currentParserIndex = parserIndex;

	// let resolve: any = null;
	// let reject: any = null;

	// const promise = new Promise((promiseResolve, promiseReject) => {
	//   resolve = promiseResolve;
	//   reject = promiseReject;
	// });

	// worker.postMessage({ text, index, parserType });

	// worker.onmessage = event => {
	//   if (currentParserIndex === parserIndex) {
	//     resolve(event.data);
	//   } else {
	//     reject();
	//   }
	// };

	// return promise as Promise<IParseResult>;
	return mysqlParser(text, index);
};

function returnCompletionItemsByVersion(value: ICompletionItem[], monacoVersion: IMonacoVersion) {
	switch (monacoVersion) {
		case '0.13.2':
			return value;
		case '0.15.6':
			return {
				suggestions: value,
			};
		default:
			throw Error('Not supported version');
	}
}

function getSeverityByVersion(monaco: any, monacoVersion: IMonacoVersion) {
	switch (monacoVersion) {
		case '0.13.2':
			return monaco.Severity.Error;
		case '0.15.6':
			return monaco.MarkerSeverity.Error;
		default:
			throw Error('Not supported version');
	}
}
